{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T12:41:38.776803Z",
     "start_time": "2025-01-17T12:41:34.294798Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.0\n",
      "torch 2.5.1+cpu\n",
      "cpu\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 加载数据"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T12:41:40.573360Z",
     "start_time": "2025-01-17T12:41:38.778810Z"
    }
   },
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "\n",
    "# fashion_mnist图像分类数据集\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 当然也可以用 torch.utils.data.Dataset 实现人为划分\n",
    "# 从数据集到dataloader\n",
    "train_loader = torch.utils.data.DataLoader(train_ds, batch_size=16, shuffle=True)\n",
    "val_loader = torch.utils.data.DataLoader(test_ds, batch_size=16, shuffle=False)"
   ],
   "outputs": [],
   "execution_count": 2
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T12:41:40.580035Z",
     "start_time": "2025-01-17T12:41:40.574362Z"
    }
   },
   "source": [
    "from torchvision.transforms import Normalize\n",
    "\n",
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img.mean(dim=(1, 2))\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "\n",
    "# print(cal_mean_std(train_ds))\n",
    "# 0.2860， 0.3205\n",
    "transforms = nn.Sequential(\n",
    "    Normalize([0.2860], [0.3205])\n",
    ")\n"
   ],
   "outputs": [],
   "execution_count": 3
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型\n",
    "\n",
    "这里我们没有用`nn.Linear`的默认初始化，而是采用了xavier均匀分布去初始化全连接层的权重\n",
    "\n",
    "xavier初始化出自论文 《Understanding the difficulty of training deep feedforward neural networks》，适用于使用`tanh`和`sigmoid`激活函数的方法。当然，我们这里的模型采用的是`relu`激活函数，采用He初始化（何凯明初始化）会更加合适。感兴趣的同学可以自己动手修改并比对效果。\n",
    "\n",
    "|神经网络层数|初始化方式|early stop at epoch| val_loss | vla_acc|\n",
    "|-|-|-|-|-|\n",
    "|20|默认|\n",
    "|20|xaviier_uniform|\n",
    "|20|he_uniform|\n",
    "|...|\n",
    "\n",
    "He初始化出自论文 《Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification》"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T12:41:40.601586Z",
     "start_time": "2025-01-17T12:41:40.581066Z"
    }
   },
   "source": [
    "class NeuralNetwork(nn.Module):\n",
    "    def __init__(self, layers_num=2):\n",
    "        super().__init__()\n",
    "        self.transforms = transforms\n",
    "        self.flatten = nn.Flatten()\n",
    "        # 多加几层\n",
    "        self.linear_relu_stack = nn.Sequential(\n",
    "            nn.Linear(28 * 28, 100),  # in_features=784, out_features=300\n",
    "            nn.ReLU(),\n",
    "            nn.AlphaDropout(p=0.2) # 增加dropout，p=0.2表示以0.2的概率将某些神经元置0，防止过拟合,且AlphaDropout不会改变输入的均值和方差\n",
    "        )\n",
    "        # 加19层\n",
    "        for i in range(1, layers_num):\n",
    "            self.linear_relu_stack.add_module(f\"Linear_{i}\", nn.Linear(100, 100))\n",
    "            self.linear_relu_stack.add_module(f\"relu\", nn.ReLU())\n",
    "            self.linear_relu_stack.add_module(f\"AlphaDropout_{i}\", nn.AlphaDropout)\n",
    "            # 增加dropout，p=0.2表示以0.2的概率将某些神经元置0，防止过拟合,且AlphaDropout不会改变输入的均值和方差\n",
    "\n",
    "            if i<3:\n",
    "                # self.linear_relu_stack.add_module(f'drop_put_{i}',nn.Dropout(p=0.2))\n",
    "                pass\n",
    "        # 输出层\n",
    "        self.linear_relu_stack.add_module(\"Output Layer\", nn.Linear(100, 10))\n",
    "        \n",
    "        # 初始化权重\n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, nn.Linear):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "\n",
    "    def forward(self, x):\n",
    "        # x.shape [batch size, 1, 28, 28]\n",
    "        x = self.transforms(x)\n",
    "        x = self.flatten(x)  \n",
    "        # 展平后 x.shape [batch size, 28 * 28]\n",
    "        logits = self.linear_relu_stack(x)\n",
    "        # logits.shape [batch size, 10]\n",
    "        return logits\n",
    "\n",
    "print(f\"{'layer_name':^40}\\tparamerters num\")\n",
    "for idx, (key, value) in enumerate(NeuralNetwork(20).named_parameters()):\n",
    "    print(\"{:<40}\\t{:^10}\".format(key, np.prod(value.shape)))"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "               layer_name               \tparamerters num\n",
      "linear_relu_stack.0.weight              \t  78400   \n",
      "linear_relu_stack.0.bias                \t   100    \n",
      "linear_relu_stack.Linear_1.weight       \t  10000   \n",
      "linear_relu_stack.Linear_1.bias         \t   100    \n",
      "linear_relu_stack.Linear_2.weight       \t  10000   \n",
      "linear_relu_stack.Linear_2.bias         \t   100    \n",
      "linear_relu_stack.Linear_3.weight       \t  10000   \n",
      "linear_relu_stack.Linear_3.bias         \t   100    \n",
      "linear_relu_stack.Linear_4.weight       \t  10000   \n",
      "linear_relu_stack.Linear_4.bias         \t   100    \n",
      "linear_relu_stack.Linear_5.weight       \t  10000   \n",
      "linear_relu_stack.Linear_5.bias         \t   100    \n",
      "linear_relu_stack.Linear_6.weight       \t  10000   \n",
      "linear_relu_stack.Linear_6.bias         \t   100    \n",
      "linear_relu_stack.Linear_7.weight       \t  10000   \n",
      "linear_relu_stack.Linear_7.bias         \t   100    \n",
      "linear_relu_stack.Linear_8.weight       \t  10000   \n",
      "linear_relu_stack.Linear_8.bias         \t   100    \n",
      "linear_relu_stack.Linear_9.weight       \t  10000   \n",
      "linear_relu_stack.Linear_9.bias         \t   100    \n",
      "linear_relu_stack.Linear_10.weight      \t  10000   \n",
      "linear_relu_stack.Linear_10.bias        \t   100    \n",
      "linear_relu_stack.Linear_11.weight      \t  10000   \n",
      "linear_relu_stack.Linear_11.bias        \t   100    \n",
      "linear_relu_stack.Linear_12.weight      \t  10000   \n",
      "linear_relu_stack.Linear_12.bias        \t   100    \n",
      "linear_relu_stack.Linear_13.weight      \t  10000   \n",
      "linear_relu_stack.Linear_13.bias        \t   100    \n",
      "linear_relu_stack.Linear_14.weight      \t  10000   \n",
      "linear_relu_stack.Linear_14.bias        \t   100    \n",
      "linear_relu_stack.Linear_15.weight      \t  10000   \n",
      "linear_relu_stack.Linear_15.bias        \t   100    \n",
      "linear_relu_stack.Linear_16.weight      \t  10000   \n",
      "linear_relu_stack.Linear_16.bias        \t   100    \n",
      "linear_relu_stack.Linear_17.weight      \t  10000   \n",
      "linear_relu_stack.Linear_17.bias        \t   100    \n",
      "linear_relu_stack.Linear_18.weight      \t  10000   \n",
      "linear_relu_stack.Linear_18.bias        \t   100    \n",
      "linear_relu_stack.Linear_19.weight      \t  10000   \n",
      "linear_relu_stack.Linear_19.bias        \t   100    \n",
      "linear_relu_stack.Output Layer.weight   \t   1000   \n",
      "linear_relu_stack.Output Layer.bias     \t    10    \n"
     ]
    }
   ],
   "execution_count": 4
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T12:41:40.661553Z",
     "start_time": "2025-01-17T12:41:40.603593Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "outputs": [],
   "execution_count": 5
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T12:41:44.258953Z",
     "start_time": "2025-01-17T12:41:40.662566Z"
    }
   },
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ],
   "outputs": [],
   "execution_count": 6
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T12:41:44.266529Z",
     "start_time": "2025-01-17T12:41:44.259957Z"
    }
   },
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ],
   "outputs": [],
   "execution_count": 7
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T12:41:44.273976Z",
     "start_time": "2025-01-17T12:41:44.268035Z"
    }
   },
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ],
   "outputs": [],
   "execution_count": 8
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T13:00:09.809295Z",
     "start_time": "2025-01-17T12:41:44.274981Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                    \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 100\n",
    "\n",
    "model = NeuralNetwork(layers_num=10)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用SGD\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "tensorboard_callback = TensorBoardCallback(\"runs/dropout\")\n",
    "tensorboard_callback.draw_model(model, [1, 28, 28])\n",
    "# 2. save best\n",
    "save_ckpt_callback = SaveCheckpointsCallback(\"checkpoints/dropout\", save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=10, min_delta=0.001)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=tensorboard_callback,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_loader)\n",
    "    )"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/375000 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "bc6ef4b898924ad5b95ccdadf89f6311"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Early stop at epoch 48 / global_step 180000\n"
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T13:00:10.131109Z",
     "start_time": "2025-01-17T13:00:09.809295Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(6 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=10000)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1200x500 with 2 Axes>"
      ],
      "image/png": "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GzbMbx2dvkzn/o6KijLbSUxMlOvXr2cbjb1ly5ZmpLz69evLF198UWSfy8SJE7OV+e677/a+np6eLi+++KJUrFhRoqOj5YknnpATJ07YOibdRtaY9KFxOKme1q9fL4899phUr17dlFGntfOl4xXqNHnVqlWTyMhI6dSpk/z1119+6/z333/Sv39/iYmJkXLlysmgQYPk4sWLfuts375dHnroIVPGWrVqyfTp07OVZcmSJWa/0HWaNWsmq1atKnBZ8oopIyNDRo8ebbZ/++23m3USEhLkn3/+ybN+p02bZsuY1IABA7KVt2vXrraup/zEldN3TB8zZsywbV3B3sj3RZcb3Zjr3ZLvyfXOyPV5xeXUfL8+1HO9FSIWLlxoRUREWElJSdauXbus5557zipXrpx14sSJYi9Lly5drLlz51o7d+60fv/9d+uRRx6x7rzzTuvixYveddq3b2/KeOzYMe/j3Llz3tevX79uNW3a1OrUqZO1detWa9WqVValSpWsMWPGeNf5+++/raioKGvUqFHWH3/8Yc2aNcsKDw+3Vq9eXSSfy4QJE6x77rnHr8ynTp3yvj5s2DCrVq1aVkpKipWWlmY98MADVtu2bW0d08mTJ/3iSU5O1tHyrXXr1jmqnvR9X3vtNWvp0qWm/MuWLfN7fdq0aVbZsmWt5cuXW9u2bbMef/xxq27dutaVK1e863Tt2tVq3ry59fPPP1sbNmyw6tevb/Xr18/7usZdpUoVq3///mbf/uqrr6zIyEjr448/9q7z008/mdimT59uYn399det2267zdqxY0eBypJXTGfPnjWf+aJFi6zdu3dbmzZtslq3bm3Fxsb6baN27drW5MmT/erP93top5jUM888Y+rBt7z//fef3zp2q6f8xOUbjz50Pw8LC7P27dtn27qCfZHvizY3ujHXuyXfk+udkevdmu9XhXiuD5lGtX7JXnzxRe/zzMxMq3r16tbUqVOtYNMDue58P/zwg3eZHrxHjhyZ69/ojluiRAnr+PHj3mVz5syxYmJirKtXr5rnr776qkl8vvr27WuSfFF8Lppo9cudEz3w6Q69ZMkS77I///zTxK0HQbvGlJXWyV133WXduHHDsfWU9UCnsVStWtWaMWOGX32VKlXKHKyUHpT073799VfvOt9++605GB49etQ8//DDD63y5ct741KjR4+2GjVq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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 10
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-17T13:00:11.573292Z",
     "start_time": "2025-01-17T13:00:10.132110Z"
    }
   },
   "source": [
    "# dataload for evaluating\n",
    "#推理时alphadropout的p值是0，通过加dropout，一定程度解决了过拟合\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(\"checkpoints/dropout/best.ckpt\", weights_only=True,map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, val_loader, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.3316\n",
      "accuracy: 0.8864\n"
     ]
    }
   ],
   "execution_count": 11
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
